package cc.z8g.browser.core

import android.app.Activity
import android.app.AlertDialog
import android.content.ActivityNotFoundException
import android.content.Intent
import android.content.pm.ActivityInfo
import android.graphics.drawable.ColorDrawable
import android.net.Uri
import android.os.Bundle
import android.view.KeyEvent
import android.view.LayoutInflater
import android.view.Menu
import android.view.MenuItem
import android.view.View
import android.view.WindowManager
import android.widget.AdapterView
import android.widget.FrameLayout
import android.widget.ImageView
import android.widget.LinearLayout
import androidx.activity.addCallback
import androidx.activity.result.contract.ActivityResultContracts
import androidx.annotation.DrawableRes
import androidx.annotation.MenuRes
import androidx.core.content.ContextCompat
import androidx.core.view.isVisible
import androidx.drawerlayout.widget.DrawerLayout
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.ListAdapter
import cc.z8g.browser.R
import cc.z8g.browser.ThemableBrowserActivity
import cc.z8g.browser.core.bookmark.BookmarkRecyclerViewAdapter
import cc.z8g.browser.core.bookmark.FaviconImageLoader
import cc.z8g.browser.core.config.ColorAnimator
import cc.z8g.browser.core.config.KeyCombos
import cc.z8g.browser.core.config.MenuItems
import cc.z8g.browser.core.search.IntentExtractor
import cc.z8g.browser.core.search.SearchListener
import cc.z8g.browser.core.search.StyleRemovingTextWatcher
import cc.z8g.browser.core.tab.DrawerTabRecyclerViewAdapter
import cc.z8g.browser.core.tab.TabPager
import cc.z8g.browser.core.tab.TabViewHolder
import cc.z8g.browser.core.tab.TabViewState
import cc.z8g.browser.core.view.LongPress
import cc.z8g.browser.core.view.WebViewLongPressHandler
import cc.z8g.browser.core.view.WebViewScrollCoordinator
import cc.z8g.browser.database.Bookmark
import cc.z8g.browser.database.HistoryEntry
import cc.z8g.browser.database.SearchSuggestion
import cc.z8g.browser.database.WebPage
import cc.z8g.browser.databinding.BrowserActivityBinding
import cc.z8g.browser.dialog.BrowserDialog
import cc.z8g.browser.dialog.BrowserDialog.resizeAndShow
import cc.z8g.browser.dialog.DialogBuilder
import cc.z8g.browser.dialog.DialogItem
import cc.z8g.browser.search.suggestions.SuggestionsAdapter
import cc.z8g.browser.ssl.createSslDrawableForState
import cc.z8g.browser.utils.DrawableUtils
import cc.z8g.browser.utils.FileUtils
import cc.z8g.browser.utils.MiscUtils
import cc.z8g.browser.utils.SystemServiceManager
import cc.z8g.browser.utils.sp.UserSp
import cc.z8g.browser.utils.value


/**
 * The base browser activity that governs the browsing experience for both default and incognito
 * browsers.
 */
abstract class BrowserActivity : ThemableBrowserActivity() {

    private lateinit var binding: BrowserActivityBinding
    private lateinit var tabsAdapter: ListAdapter<TabViewState, TabViewHolder>
    private lateinit var bookmarksAdapter: BookmarkRecyclerViewAdapter

    private var menuItemShare: MenuItem? = null
    private var menuItemCopyLink: MenuItem? = null
    private var menuItemAddToHome: MenuItem? = null
    private var menuItemAddBookmark: MenuItem? = null

    private val defaultColor by lazy { ContextCompat.getColor(this, R.color.primary_color) }
    private val backgroundDrawable by lazy { ColorDrawable(defaultColor) }

    private var customView: View? = null

    @Suppress("ConvertLambdaToReference")
    private val launcher = registerForActivityResult(
        ActivityResultContracts.StartActivityForResult()
    ) { presenter.onFileChooserResult(it) }

    internal lateinit var presenter: BrowserPresenter
    private lateinit var browserFrame: FrameLayout
    private lateinit var toolbarRoot: LinearLayout
    private lateinit var toolbar: View

    internal lateinit var tabPager: TabPager

    /**
     * True if the activity is operating in incognito mode, false otherwise.
     */
    abstract fun isIncognito(): Boolean

    /**
     * Provide the menu used by the browser instance.
     */
    @MenuRes
    abstract fun menuId(): Int

    /**
     * 公共菜单文件
     */
    @MenuRes
    protected fun commonMenuId(): Int = R.menu.common

    /**
     * Provide the home icon used by the browser instance.
     */
    @DrawableRes
    abstract fun homeIcon(): Int

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = BrowserActivityBinding.inflate(LayoutInflater.from(this))

        setContentView(binding.root)
        setSupportActionBar(binding.toolbar)

        browserFrame = binding.contentFrame
        toolbarRoot = binding.uiLayout
        toolbar = binding.toolbarLayout

        val webViewScrollCoordinator = WebViewScrollCoordinator(this, browserFrame, toolbarRoot, toolbar)
        val webViewLongPressHandler = WebViewLongPressHandler(this)
        tabPager = TabPager(browserFrame, webViewScrollCoordinator, webViewLongPressHandler)

        val initialUrl: String? = (IntentExtractor.extractUrlFromIntent(intent) as? BrowserContract.Action.LoadUrl)?.url

        val incognitoMode = isIncognito()
        presenter = BrowserPresenter(this, this, tabPager, initialUrl, incognitoMode)
        binding.drawerLayout.addDrawerListener(object : DrawerLayout.SimpleDrawerListener() {

            override fun onDrawerOpened(drawerView: View) {
                if (drawerView == binding.tabDrawer) {
                    presenter.onTabDrawerMoved(isOpen = true)
                } else if (drawerView == binding.bookmarkDrawer) {
                    presenter.onBookmarkDrawerMoved(isOpen = true)
                }
            }

            override fun onDrawerClosed(drawerView: View) {
                if (drawerView == binding.tabDrawer) {
                    presenter.onTabDrawerMoved(isOpen = false)
                } else if (drawerView == binding.bookmarkDrawer) {
                    presenter.onBookmarkDrawerMoved(isOpen = false)
                }
            }
        })

//        binding.(bookmarkDrawer/tabDrawer).layoutParams.gravity=Gravity.(START/END) 实现书签与标签页换位

        binding.homeImageView.apply {
            isVisible = isIncognito()
            setImageResource(homeIcon())
        }
        binding.tabCountView.isVisible = !isIncognito()

        tabsAdapter = DrawerTabRecyclerViewAdapter(presenter::onTabClick, presenter::onTabLongClick, presenter::onTabClose)
        binding.drawerTabsList.apply {
            isVisible = true
            adapter = tabsAdapter
            layoutManager = LinearLayoutManager(this@BrowserActivity)
        }

        bookmarksAdapter = BookmarkRecyclerViewAdapter(presenter::onBookmarkClick, presenter::onBookmarkLongClick, FaviconImageLoader(this))
        binding.bookmarkListView.adapter = bookmarksAdapter
        binding.bookmarkListView.layoutManager = LinearLayoutManager(this)

        presenter.onViewAttached(BrowserStateAdapter(this))

        val search = binding.search
        val suggestionsAdapter = SuggestionsAdapter(this, isIncognito = isIncognito()).apply {
            onSuggestionInsertClick = {
                if (it is SearchSuggestion) {
                    search.setText(it.title)
                    search.setSelection(it.title.length)
                } else {
                    search.setText(it.url)
                    search.setSelection(it.url.length)
                }
            }
        }
        search.onItemClickListener = AdapterView.OnItemClickListener { _, _, position, _ ->
            search.clearFocus()
            presenter.onSearchSuggestionClicked(suggestionsAdapter.getItem(position) as WebPage)
            SystemServiceManager.inputMethodManager.hideSoftInputFromWindow(binding.root.windowToken, 0)
        }
        search.setAdapter(suggestionsAdapter)
        val searchListener = SearchListener(
            onConfirm = { presenter.onSearch(search.text.toString()) },
            inputMethodManager = SystemServiceManager.inputMethodManager
        )
        search.setOnEditorActionListener(searchListener)
        search.setOnKeyListener(searchListener)
        search.addTextChangedListener(StyleRemovingTextWatcher())
        search.setOnFocusChangeListener { _, hasFocus ->
            presenter.onSearchFocusChanged(hasFocus)
            search.selectAll()
        }

        binding.findPrevious.setOnClickListener { presenter.onFindPrevious() }
        binding.findNext.setOnClickListener { presenter.onFindNext() }
        binding.findQuit.setOnClickListener { presenter.onFindDismiss() }

        binding.homeButton.setOnClickListener { presenter.onTabCountViewClick() }
        binding.actionBack.setOnClickListener { presenter.onBackClick() }
        binding.actionForward.setOnClickListener { presenter.onForwardClick() }
        binding.actionHome.setOnClickListener { presenter.onHomeClick() }
        binding.newTabButton.setOnClickListener { presenter.onNewTabClick() }
        binding.newTabButton.setOnLongClickListener {
            presenter.onNewTabLongClick()
            true
        }
        binding.searchRefresh.setOnClickListener { presenter.onRefreshOrStopClick() }
        binding.actionAddBookmark.setOnClickListener { presenter.onStarClick() }
//        binding.actionPageTools.setOnClickListener { presenter.onToolsClick() }
        binding.tabHeaderButton.setOnClickListener { presenter.onTabMenuClick() }
        binding.bookmarkBackButton.setOnClickListener { presenter.onBookmarkMenuClick() }
        binding.searchSslStatus.setOnClickListener { presenter.onSslIconClick() }

        tabPager.longPressListener = presenter::onPageLongPress

        onBackPressedDispatcher.addCallback {
            presenter.onNavigateBack()
        }
    }

    override fun onNewIntent(intent: Intent?) {
        intent?.let(IntentExtractor::extractUrlFromIntent)?.let(presenter::onNewAction)
        super.onNewIntent(intent)
    }

    override fun onDestroy() {
        super.onDestroy()
        presenter.onViewDetached()
    }

    override fun onStop() {
        super.onStop()
    }

    override fun onPause() {
        super.onPause()
        presenter.onViewHidden()
    }

    override fun onCreateOptionsMenu(menu: Menu): Boolean {
        menuInflater.inflate(commonMenuId(), menu) // 加载公共的菜单文件
        menuInflater.inflate(menuId(), menu)
        menuItemShare = menu.findItem(R.id.action_share)
        menuItemCopyLink = menu.findItem(R.id.action_copy)
        menuItemAddBookmark = menu.findItem(R.id.action_add_bookmark)
        return super.onCreateOptionsMenu(menu)
    }

    override fun onOptionsItemSelected(item: MenuItem): Boolean {
        return MenuItems.adaptMenuItem(item)?.let(presenter::onMenuClick)?.let { true }
            ?: super.onOptionsItemSelected(item)
    }

    override fun onKeyUp(keyCode: Int, event: KeyEvent): Boolean {
        return KeyCombos.adaptKeyEvent(event)?.let(presenter::onKeyComboClick)?.let { true }
            ?: super.onKeyUp(keyCode, event)
    }

    /**
     * @see BrowserContract.View.renderState
     */
    fun renderState(needUpdateState: PartialBrowserViewState) {
        needUpdateState.isBackEnabled?.let { binding.actionBack.isEnabled = it }
        needUpdateState.isForwardEnabled?.let { binding.actionForward.isEnabled = it }
        needUpdateState.displayUrl?.let(binding.search::setText)
        needUpdateState.sslState?.let {
            binding.searchSslStatus.setImageDrawable(createSslDrawableForState(it))
            binding.searchSslStatus.updateVisibilityForDrawable()
        }
        needUpdateState.enableFullMenu?.let {
            menuItemShare?.isVisible = it
            menuItemCopyLink?.isVisible = it
            menuItemAddToHome?.isVisible = it
            menuItemAddBookmark?.isVisible = it
        }
        needUpdateState.themeColor?.value()?.let(::animateColorChange)
        needUpdateState.isRefresh?.let {
            binding.searchRefresh.setImageResource(if (it) R.drawable.ic_action_refresh else R.drawable.ic_action_delete)
        }
        needUpdateState.bookmarks?.let(bookmarksAdapter::submitList)
        needUpdateState.isBookmarked?.let { binding.actionAddBookmark.setImageResource(if (it) R.drawable.ic_bookmark else R.drawable.ic_action_star) }
        needUpdateState.isBookmarkEnabled?.let { binding.actionAddBookmark.isEnabled = it }
        needUpdateState.isRootFolder?.let { binding.bookmarkBackButton.setImageResource(if (it) R.drawable.ic_bookmark else R.drawable.ic_action_back) }
        needUpdateState.findInPage?.let {
            if (it.isEmpty()) {
                binding.findBar.isVisible = false
            } else {
                binding.findBar.isVisible = true
                binding.findQuery.text = it
            }
        }
    }

    /**
     * @see BrowserContract.View.renderTabs
     */
    fun renderTabs(tabListState: List<TabViewState>) {
        binding.tabCountView.updateCount(tabListState.size)
        tabsAdapter.submitList(tabListState)
    }

    /**
     * @see BrowserContract.View.showAddBookmarkDialog
     */
    fun showAddBookmarkDialog(title: String, url: String, folders: List<String>) {
        DialogBuilder.showAddBookmarkDialog(
            activity = this,
            currentTitle = title,
            currentUrl = url,
            folders = folders,
            onSave = presenter::onBookmarkConfirmed
        )
    }

    /**
     * @see BrowserContract.View.showBookmarkOptionsDialog
     */
    fun showBookmarkOptionsDialog(bookmark: Bookmark.Entry) {
        DialogBuilder.showLongPressedDialogForBookmarkUrl(
            activity = this,
            onClick = {
                presenter.onBookmarkOptionClick(bookmark, it)
            }
        )
    }

    /**
     * @see BrowserContract.View.showEditBookmarkDialog
     */
    fun showEditBookmarkDialog(title: String, url: String, folder: String, folders: List<String>) {
        DialogBuilder.showEditBookmarkDialog(
            activity = this,
            currentTitle = title,
            currentUrl = url,
            currentFolder = folder,
            folders = folders,
            onSave = presenter::onBookmarkEditConfirmed
        )
    }

    /**
     * @see BrowserContract.View.showFolderOptionsDialog
     */
    fun showFolderOptionsDialog(folder: Bookmark.Folder) {
        DialogBuilder.showBookmarkFolderLongPressedDialog(
            activity = this,
            onClick = {
                presenter.onFolderOptionClick(folder, it)
            }
        )
    }

    /**
     * @see BrowserContract.View.showEditFolderDialog
     */
    fun showEditFolderDialog(oldTitle: String) {
        DialogBuilder.showRenameFolderDialog(
            activity = this,
            oldTitle = oldTitle,
            onSave = presenter::onBookmarkFolderRenameConfirmed
        )
    }
    /**
     * @see BrowserContract.View.showHistoryOptionsDialog
     */
    fun showHistoryOptionsDialog(historyEntry: HistoryEntry) {
        DialogBuilder.showLongPressedHistoryLinkDialog(
            activity = this,
            onClick = {
                presenter.onHistoryOptionClick(historyEntry, it)
            }
        )
    }

    /**
     * @see BrowserContract.View.showFindInPageDialog
     */
    fun showFindInPageDialog() {
        BrowserDialog.showEditText(
            this,
            R.string.action_find,
            R.string.search_hint,
            R.string.search_hint,
            presenter::onFindInPage
        )
    }

    /**
     * @see BrowserContract.View.showLinkLongPressDialog
     */
    fun showLinkLongPressDialog(longPress: LongPress) {
        BrowserDialog.show(this, longPress.targetUrl?.replace(BrowserConst.HTTP, ""),
            DialogItem(title = R.string.dialog_open_new_tab) {
                presenter.onLinkLongPressEvent(longPress, BrowserConst.LINK_LONG_PRESS_NEW_TAB)
            },
            DialogItem(title = R.string.dialog_open_background_tab) {
                presenter.onLinkLongPressEvent(longPress, BrowserConst.LINK_LONG_PRESS_BACKGROUND_TAB)
            },
            DialogItem(title = R.string.dialog_open_incognito_tab, isConditionMet = !isIncognito()) {
                presenter.onLinkLongPressEvent(longPress, BrowserConst.LINK_LONG_PRESS_INCOGNITO_TAB)
            },
            DialogItem(title = R.string.action_share) {
                presenter.onLinkLongPressEvent(longPress, BrowserConst.LINK_LONG_PRESS_SHARE)
            },
            DialogItem(title = R.string.dialog_copy_link) {
                presenter.onLinkLongPressEvent(longPress, BrowserConst.LINK_LONG_PRESS_COPY_LINK)
            })
    }

    /**
     * @see BrowserContract.View.showImageLongPressDialog
     */
    fun showImageLongPressDialog(longPress: LongPress) {
        BrowserDialog.show(this, longPress.targetUrl?.replace(BrowserConst.HTTP, ""),
            DialogItem(title = R.string.dialog_open_new_tab) {
                presenter.onImageLongPressEvent(longPress, BrowserConst.IMAGE_LONG_PRESS_NEW_TAB)
            },
            DialogItem(title = R.string.dialog_open_background_tab) {
                presenter.onImageLongPressEvent(longPress, BrowserConst.IMAGE_LONG_PRESS_BACKGROUND_TAB)
            },
            DialogItem(title = R.string.dialog_open_incognito_tab, isConditionMet = !isIncognito()) {
                presenter.onImageLongPressEvent(longPress, BrowserConst.IMAGE_LONG_PRESS_INCOGNITO_TAB)
            },
            DialogItem(title = R.string.action_share) {
                presenter.onImageLongPressEvent(longPress, BrowserConst.IMAGE_LONG_PRESS_SHARE)
            },
            DialogItem(title = R.string.dialog_copy_link) {
                presenter.onImageLongPressEvent(longPress, BrowserConst.IMAGE_LONG_PRESS_COPY_LINK)
            },
            DialogItem(title = R.string.dialog_download_image) {
                presenter.onImageLongPressEvent(longPress, BrowserConst.IMAGE_LONG_PRESS_DOWNLOAD)
            })
    }

    /**
     * @see BrowserContract.View.showCloseBrowserDialog
     */
    fun showCloseBrowserDialog(id: Int) {
        BrowserDialog.show(
            this, R.string.dialog_title_close_browser,
            DialogItem(title = R.string.close_after_tabs) {
                presenter.onCloseBrowserEvent(id, BrowserConst.CLOSE_TAB_AFTER)
            },
            DialogItem(title = R.string.close_other_tabs) {
                presenter.onCloseBrowserEvent(id, BrowserConst.CLOSE_TAB_OTHERS)
            },
            DialogItem(title = R.string.close_all_tabs) {
                presenter.onCloseBrowserEvent(id, BrowserConst.CLOSE_TAB_ALL)
            }
        )
    }

    /**
     * @see BrowserContract.View.openBookmarkDrawer
     */
    fun openBookmarkDrawer() {
        binding.drawerLayout.closeDrawer(binding.tabDrawer)
        binding.drawerLayout.openDrawer(binding.bookmarkDrawer)
    }

    /**
     * @see BrowserContract.View.closeBookmarkDrawer
     */
    fun closeBookmarkDrawer() {
        binding.drawerLayout.closeDrawer(binding.bookmarkDrawer)
    }

    /**
     * @see BrowserContract.View.openTabDrawer
     */
    fun openTabDrawer() {
        binding.drawerLayout.closeDrawer(binding.bookmarkDrawer)
        binding.drawerLayout.openDrawer(binding.tabDrawer)
    }

    /**
     * @see BrowserContract.View.closeTabDrawer
     */
    fun closeTabDrawer() {
        binding.drawerLayout.closeDrawer(binding.tabDrawer)
    }

    /**
     * @see BrowserContract.View.showToolbar
     */
    fun showToolbar() {
        tabPager.showToolbar()
    }

    /**
     * @see BrowserContract.View.showLocalFileBlockedDialog
     */
    fun showLocalFileBlockedDialog() {
        AlertDialog.Builder(this)
            .setCancelable(true)
            .setTitle(R.string.title_warning)
            .setMessage(R.string.message_blocked_local)
            .setNegativeButton(android.R.string.cancel) { _, _ ->
                presenter.onConfirmOpenLocalFile(allow = false)
            }
            .setPositiveButton(R.string.action_open) { _, _ ->
                presenter.onConfirmOpenLocalFile(allow = true)
            }
            .setOnCancelListener { presenter.onConfirmOpenLocalFile(allow = false) }
            .resizeAndShow()
    }

    /**
     * @see BrowserContract.View.showFileChooser
     */
    fun showFileChooser(intent: Intent) {
        launcher.launch(intent)
    }

    /**
     * @see BrowserContract.View.showCustomView
     */
    fun showCustomView(view: View) {
        requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_USER_LANDSCAPE
        binding.root.addView(view)
        customView = view
        setFullscreen(enabled = true, immersive = true)
    }

    /**
     * @see BrowserContract.View.hideCustomView
     */
    fun hideCustomView() {
        requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED
        customView?.let(binding.root::removeView)
        customView = null
        setFullscreen(enabled = false, immersive = false)
    }

    /**
     * @see BrowserContract.View.clearSearchFocus
     */
    fun clearSearchFocus() {
        binding.search.clearFocus()
    }

    // TODO: update to use non deprecated flags
    private fun setFullscreen(enabled: Boolean, immersive: Boolean) {
        val window = window
        val decor = window.decorView
        if (enabled) {
            if (immersive) {
                decor.systemUiVisibility = (View.SYSTEM_UI_FLAG_LAYOUT_STABLE
                        or View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
                        or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
                        or View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
                        or View.SYSTEM_UI_FLAG_FULLSCREEN
                        or View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY)
            } else {
                decor.systemUiVisibility = View.SYSTEM_UI_FLAG_VISIBLE
            }
            window.setFlags(
                WindowManager.LayoutParams.FLAG_FULLSCREEN,
                WindowManager.LayoutParams.FLAG_FULLSCREEN
            )
        } else {
            window.clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN)
            decor.systemUiVisibility = View.SYSTEM_UI_FLAG_VISIBLE
        }
    }

    private fun animateColorChange(color: Int) {
        if (isIncognito() || !UserSp.getBoolean(UserSp.KEY_THEME_COLOR)
            || UserSp.getInt(UserSp.KEY_THEME) != UserSp.THEME_LIGHT) {
            return
        }
        val colorAnimator = ColorAnimator(defaultColor)
        binding.toolbar.startAnimation(colorAnimator.animateTo(color) { mainColor, secondaryColor ->
            backgroundDrawable.color = mainColor
            window.setBackgroundDrawable(backgroundDrawable)
            binding.toolbar.setBackgroundColor(mainColor)
            binding.searchContainer.background?.let { DrawableUtils.tint(it, secondaryColor) }
        })
    }

    private fun ImageView.updateVisibilityForDrawable() {
        visibility = if (drawable == null) {
            View.GONE
        } else {
            View.VISIBLE
        }
    }

    @Deprecated("Deprecated in Java")
    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        val urlList = ArrayList<String>()
        if (requestCode == REQUEST_CODE_OPEN_DOWNLOADS && resultCode == Activity.RESULT_OK && data != null) {
            data.clipData?.let {
                for (i in 0 until it.itemCount) {
                    urlList.add(it.getItemAt(i).uri.toString())
                }
            }
            data.data?.let {
                urlList.add(it.toString())
            }
        }
        if (urlList.isEmpty()) {
            MiscUtils.showToast(this, R.string.action_message_canceled)
        } else {
            for (url in urlList) {
                this.presenter.onNewAction(BrowserContract.Action.LoadUrl(url))
            }
        }
        super.onActivityResult(requestCode, resultCode, data)
    }

    /** 打开下载内容 */
    fun openDownloads() {
        val activity = this
        val directory = FileUtils.getDefaultDownloadDir();
        if (directory.isDirectory()) {
            val intent = Intent(Intent.ACTION_OPEN_DOCUMENT)
            intent.addCategory(Intent.CATEGORY_OPENABLE)
            intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true)
            intent.setDataAndType(Uri.parse(directory.absolutePath), "*/*")
            try {
                activity.startActivityForResult(intent, REQUEST_CODE_OPEN_DOWNLOADS)
            } catch (e: ActivityNotFoundException) {
                // 处理没有文件管理器应用的情况
            }
        } else {

        }
    }

    companion object {
        private const val REQUEST_CODE_OPEN_DOWNLOADS = 101;
    }
}
